//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using OpenLS.Core.Serialization;

namespace OpenLS.Spreadsheet
{
    /// <summary>
    /// Gradient fill used to draw the background of a cell
    /// </summary>
    public class GradientFill: Fill
    {
        public override int GetHashCode()
        {
            int result = 0;
            result += GradientType.GetHashCode();
            result += Left.GetHashCode() + Right.GetHashCode() + Top.GetHashCode() + Bottom.GetHashCode();
            foreach (GradientStop s in Stops)
                result += s.GetHashCode();
            return result;
        }

        public override bool Equals(Fill fill)
        {
            if (fill == this)
                return true;
            GradientFill f = fill as GradientFill;
            if (f == null)
                return false;
            if (f.GradientType !=GradientType)
                return false;
            if (f.Left !=Left)
                return false;
            if (f.Right != Right)
                return false;
            if (f.Top != Top)
                return false;
            if (f.Bottom != Bottom)
                return false;
            if (f.Degree !=Degree)
                return false;
            if (f.Stops.Count != Stops.Count)
                return false;
            for (int i = 0; i < Stops.Count; i++)
            {
                if (!f.Stops[i].Equals(Stops[i]))
                    return false;
            }
            return true;
        }

        internal override Fill Clone()
        {
            GradientFill result = (GradientFill) this.MemberwiseClone();
            result._stops = new List<GradientStop>();
            foreach (var stop in Stops)
                result.Stops.Add(stop.Clone());
            return result;
           
        }


        internal override void ReadXmlCore(ReadContext context)
        {
            using (ReadContext c = context.Read("gradientFill"))
            {
                GradientType = c.GetOptionalEnum("type", GradientType.Linear);
                Degree = c.GetOptionalDouble("degree", 0);
                Left = c.GetOptionalDouble("left", 0);
                Right = c.GetOptionalDouble("right", 0);
                Top = c.GetOptionalDouble("top", 0);
                Bottom = c.GetOptionalDouble("bottom", 0);
                Stops.Clear();
                while (c.ReaderLocalName == "stop")
                {
                    Stops.Add(c.ReadElement<GradientStop>());
                }
            }
        }

        internal override void WriteXmlCore(WriteContext context)
        {
            using (WriteContext cFill = context.Write("fill"))
            {
                using (WriteContext c = cFill.Write("gradientFill"))
                {
                    c.SetOptionalEnum("type", GradientType, GradientType.Linear);
                    c.SetOptionalDouble("degree", Degree, 0);
                    c.SetOptionalDouble("left", Left, 0);
                    c.SetOptionalDouble("right", Right, 0);
                    c.SetOptionalDouble("top", Top, 0);
                    c.SetOptionalDouble("bottom", Bottom, 0);
                    foreach (GradientStop stop in Stops)
                        c.WriteElement(stop);
                }
            }
        }

        private List<GradientStop> _stops = new List<GradientStop>();

        public List<GradientStop> Stops
        {
            get { return _stops; }
        }
	
        private GradientType _gradientType;

        public GradientType GradientType
        {
            get { return _gradientType; }
            set { _gradientType = value; }
        }
        private double _degree;

        public double Degree
        {
            get { return _degree; }
            set { _degree = value; }
        }
        private double _left;

        public double Left
        {
            get { return _left; }
            set { _left = value; }
        }
        private double _right;

        public double Right
        {
            get { return _right; }
            set { _right = value; }
        }
        private double _top;

        public double Top
        {
            get { return _top; }
            set { _top = value; }
        }
        private double _bottom;

        public double Bottom
        {
            get { return _bottom; }
            set { _bottom = value; }
        }
	
	
	
	
	
    }
}
